/*
 * @Author: 0x9DEFA478
 * @Date: 2024-07-13 22:15:09
 * @LastEditTime: 2024-09-16 14:18:21
 * @LastEditors: 0x9DEFA478
 * @Description: 一些依赖于平台的操作接口声明
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#ifndef hLL_ASM_ARM_H_TS_LL_AtomicAccess_H_
#define hLL_ASM_ARM_H_TS_LL_AtomicAccess_H_
#include "H_Type.h"




//强制内联
#if defined __CC_ARM
#define H_TS_LL_ForceStaticInline static __forceinline
#elif defined __ARMCC_VERSION
#define H_TS_LL_ForceStaticInline __attribute__((always_inline)) static __inline
#elif defined __GNUC__
#define H_TS_LL_ForceStaticInline __attribute__((always_inline)) static inline
#else
#define H_TS_LL_ForceStaticInline static inline
#endif




/**
 * @brief ARM的LDREX指令
 * @param ValuePointer 操作地址
 * @return 读取到的值
 */
H_TS_LL_ForceStaticInline Hsize H_TS_LL_AtomicAccess_LDREX(volatile Hsize* ValuePointer){
  Hsize r;

#if defined __CC_ARM

  __schedule_barrier();
//来自于CMSIS库的相关头文件
#if (__ARMCC_VERSION < 5060020)
  r=__ldrex((volatile int*)ValuePointer);
#else
  _Pragma("push") _Pragma("diag_suppress 3731")
  r=(Hsize)__ldrex((volatile int*)ValuePointer);
  _Pragma("pop")
#endif
  __schedule_barrier();

#elif defined __ARMCC_VERSION
  __asm volatile("LDREX %[Result],[%[Address]]":[Result] "=r" (r):[Address] "r" (ValuePointer):"memory");
#elif defined __GNUC__
  asm volatile("LDREX %[Result],[%[Address]]":[Result] "=r" (r):[Address] "r" (ValuePointer):"memory");
#elif defined __ICCARM__
  __asm volatile("LDREX %[Result],[%[Address]]":[Result] "=r" (r):[Address] "r" (ValuePointer):"memory");
#else
#error "不支持的编译器"
#endif

  return r;
}

/**
 * @brief ARM的STREX指令
 * @param NewValue 新的值
 * @param ValuePointer 操作地址
 * @return 操作结果 0:成功 其他:失败
 */
H_TS_LL_ForceStaticInline Hsize H_TS_LL_AtomicAccess_STREX(Hsize NewValue,volatile Hsize* ValuePointer){
  Hsize r;

#if defined __CC_ARM

  // __schedule_barrier();
//来自于CMSIS库的相关头文件
#if (__ARMCC_VERSION < 5060020)
  r=__strex(NewValue,(volatile int*)ValuePointer);
#else
  _Pragma("push") _Pragma("diag_suppress 3731")
  r=__strex(NewValue,(volatile int*)ValuePointer);
  _Pragma("pop")
#endif
  // __schedule_barrier();

#elif defined __ARMCC_VERSION
  __asm volatile("STREX %[Result],%[Value],[%[Address]]"
    :[Result] "=&r" (r)
    :[Value] "r" (NewValue),[Address] "r" (ValuePointer)
    :"memory");
#elif defined __GNUC__
  asm volatile("STREX %[Result],%[Value],[%[Address]]"
    :[Result] "=&r" (r)
    :[Value] "r" (NewValue),[Address] "r" (ValuePointer)
    :"memory");
#elif defined __ICCARM__
  __asm volatile("STREX %[Result],%[Value],[%[Address]]"
    :[Result] "=&r" (r)
    :[Value] "r" (NewValue),[Address] "r" (ValuePointer)
    :"memory");
#else
#error "不支持的编译器"
#endif

  return r;
}




/**
 * @brief 变量设置
 * @param ValuePointer 指向变量
 * @param NewValue 变量新的值
 * @return 变量原来的值
 */
H_TS_LL_ForceStaticInline Hsize H_TS_LL_AtomicAccess_SetValue(volatile Hsize* ValuePointer,Hsize NewValue){
  Hsize r;
  
  do{
    r=H_TS_LL_AtomicAccess_LDREX(ValuePointer);
  }while(H_TS_LL_AtomicAccess_STREX(NewValue,(volatile Hsize*)ValuePointer)!=0);

  return r;
}

/**
 * @brief 向链表添加节点
 * @param List 链表
 * @param Item 待添加的项
 * @param NextOffset Next指针在结构体中的偏移
 * @return 无
 */
H_TS_LL_ForceStaticInline void H_TS_LL_AtomicAccess_ListPush(void* volatile* List,void* Item,Hsize NextOffset){
  volatile Hbyte* p;
  volatile Hbyte* item;

  item=Item;

  do{
    p=(volatile Hbyte*)H_TS_LL_AtomicAccess_LDREX((volatile Hsize*)List);
    *((void* volatile*)&item[NextOffset])=(void*)p;
  }while(H_TS_LL_AtomicAccess_STREX((Hsize)item,(volatile Hsize*)List)!=0);

}

/**
 * @brief 从链表中提取节点
 * @param List 链表
 * @param NextOffset Next指针在结构体中的偏移
 * @return 取出的节点
 */
H_TS_LL_ForceStaticInline void* H_TS_LL_AtomicAccess_ListPop(void* volatile* List,Hsize NextOffset){
  volatile Hbyte* p;
  volatile Hbyte* p_next;

  do{
    p=(volatile Hbyte*)H_TS_LL_AtomicAccess_LDREX((volatile Hsize*)List);
    if(p==NULL){
      H_TS_LL_AtomicAccess_STREX((Hsize)p,(volatile Hsize*)List);
      return (void*)p;
    }

    p_next=*((void* volatile*)&p[NextOffset]);
  }while(H_TS_LL_AtomicAccess_STREX((Hsize)p_next,(volatile Hsize*)List)!=0);

  return (void*)p;
}

/**
 * @brief 值增加 到达一定值时不增加
 * @param ValuePointer 待增加变量的地址
 * @param MaxValue 变量最大值(可达到的最大值)
 * @return 自增之前的值
 */
H_TS_LL_ForceStaticInline Husize H_TS_LL_AtomicAccess_ValueIncrement(volatile Husize* ValuePointer,Husize MaxValue){
  Husize r;
  Husize NewValue;

  do{
    r=(Husize)H_TS_LL_AtomicAccess_LDREX((volatile Hsize*)ValuePointer);

    if(r<MaxValue){
      NewValue=r+1U;
    }else{
      NewValue=r;
    }
  }while(H_TS_LL_AtomicAccess_STREX((Hsize)NewValue,(volatile Hsize*)ValuePointer)!=0);

  return r;
}

/**
 * @brief 值自减 到达0时不减少
 * @param ValuePointer 待自减变量的地址
 * @return 自减之前的值
 */
H_TS_LL_ForceStaticInline Husize H_TS_LL_AtomicAccess_ValueDecrement(volatile Husize* ValuePointer){
  Husize r;
  Husize NewValue;

  do{
    r=(Husize)H_TS_LL_AtomicAccess_LDREX((volatile Hsize*)ValuePointer);

    if(r>0){
      NewValue=r-1U;
    }else{
      NewValue=r;
    }
  }while(H_TS_LL_AtomicAccess_STREX((Hsize)NewValue,(volatile Hsize*)ValuePointer)!=0);

  return r;
}

/**
 * @brief FIFO写索引增量操作(申请写入索引)
 * @param WriteIndexPointer 指向写索引
 * @param ReadIndexPointer 指向读索引
 * @param Size 索引的范围为[0,Size)
 * @return 大于等于0: 自增成功, 为待写入的起始索引 -1:无自增空间
 */
H_TS_LL_ForceStaticInline Hsize H_TS_LL_AtomicAccess_WriteIndexIncrement(volatile Hsize* WriteIndexPointer,volatile Hsize* ReadIndexPointer,Hsize Size){
  Hsize WriteIndex;
  Hsize writeIndex;

  do{
    Hsize ReadIndex;
    Hsize size;

    WriteIndex=(Hsize)H_TS_LL_AtomicAccess_LDREX(WriteIndexPointer);
    ReadIndex=*ReadIndexPointer;

    size=ReadIndex-WriteIndex;

    if(size<0){
      size=Size-size;
    }

    if(size<=1){
      H_TS_LL_AtomicAccess_STREX(WriteIndex,WriteIndexPointer);
      return -1;
    }

    writeIndex=WriteIndex+1;
    if(writeIndex>=Size){
      writeIndex=0;
    }
  }while(H_TS_LL_AtomicAccess_STREX(writeIndex,WriteIndexPointer)!=0);

  return WriteIndex;
}




#endif //hLL_ASM_ARM_H_TS_LL_AtomicAccess_H_
